home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / lang / SmallEiffel.lha / SmallEiffel / lib_std / input_stream.e < prev    next >
Text File  |  1998-12-22  |  10KB  |  425 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://www.loria.fr/SmallEiffel
  11. --
  12. deferred class INPUT_STREAM
  13.    --
  14.    -- This abstract class is the superclass of all classes 
  15.    -- representing an input stream of bytes. 
  16.    --
  17.  
  18. feature -- State of the stream :
  19.  
  20.    is_connected: BOOLEAN is
  21.      -- True when the corresponding stream is connected
  22.      -- to some physical input device.
  23.       deferred
  24.       end;
  25.  
  26.    end_of_input: BOOLEAN is
  27.      -- Has end-of-input been reached ?
  28.      -- True when the last character has been read.
  29.       require
  30.      is_connected
  31.       deferred
  32.       end;
  33.  
  34. feature -- To read one character at a time :
  35.  
  36.    read_character is
  37.      -- Read a character and assign it to `last_character'.
  38.       require
  39.      not end_of_input
  40.       deferred
  41.       ensure
  42.      not push_back_flag
  43.       end;
  44.  
  45.    last_character: CHARACTER is
  46.      -- Last character read with `read_character'.
  47.       require
  48.      is_connected
  49.       deferred
  50.       end;
  51.    
  52.    push_back_flag: BOOLEAN;
  53.      -- True in one char is already pushed back.
  54.  
  55.    unread_character is
  56.      -- Un-read the last character read.
  57.      --
  58.       require
  59.      not push_back_flag
  60.       deferred
  61.       ensure
  62.      push_back_flag
  63.       end;
  64.  
  65. feature -- Skipping separators :
  66.  
  67.    skip_separators is
  68.      -- Stop doing `read_character' as soon as `end_of_file' is reached
  69.      -- or as soon as `last_character' is not `is_separator'.
  70.      -- When first character is already not `is_separator' nothing 
  71.      -- is done. 
  72.       do
  73.      from  
  74.      until
  75.         end_of_input or else 
  76.         not last_character.is_separator
  77.      loop
  78.         read_character;
  79.      end;
  80.       end;
  81.    
  82.    skip_separators_using(separators:STRING) is
  83.      -- Same job as `skip_separators' using `separators'.
  84.       require 
  85.      separators /= void
  86.       do
  87.      -- Implemented by : Lars Brueckner 
  88.      -- (larsbruk@rbg.informatik.th-darmstadt.de)
  89.      from 
  90.      until
  91.         end_of_input or else 
  92.         not separators.has(last_character)
  93.      loop
  94.         read_character;
  95.      end;
  96.       end;
  97.  
  98. feature -- To read one number at a time :
  99.    
  100.    read_integer is
  101.      -- Read an integer according to the Eiffel syntax.
  102.      -- Make result available in `last_integer'.
  103.      -- Heading separators are automatically skipped using 
  104.      -- `is_separator' of class CHARACTER.
  105.      -- Trailing separators are not skipped.
  106.       require
  107.      not end_of_input
  108.       local
  109.      state: INTEGER;
  110.      sign: BOOLEAN;
  111.      -- state = 0 : waiting sign or first digit.
  112.      -- state = 1 : sign read, waiting first digit.
  113.      -- state = 2 : in the number.
  114.      -- state = 3 : end state.
  115.      -- state = 4 : error state.
  116.       do
  117.      from
  118.      until
  119.         state > 2
  120.      loop
  121.         read_character;
  122.         inspect 
  123.            state
  124.         when 0 then
  125.            if last_character.is_separator then
  126.            elseif last_character.is_digit then
  127.           last_integer := last_character.value;
  128.           state := 2;
  129.            elseif last_character = '-' then
  130.           sign := true;
  131.           state := 1;
  132.            elseif last_character = '+' then
  133.           state := 1;
  134.            else
  135.           state := 4;
  136.            end;
  137.         when 1 then
  138.            if last_character.is_separator then
  139.            elseif last_character.is_digit then
  140.           last_integer := last_character.value;
  141.           state := 2;
  142.            else
  143.           state := 4;
  144.            end;
  145.         else -- 2
  146.            if last_character.is_digit then
  147.           last_integer := (last_integer * 10) + last_character.value;
  148.            else
  149.           state := 3;
  150.            end;
  151.         end;
  152.         if end_of_input then
  153.            inspect 
  154.           state
  155.            when 0 .. 1 then
  156.           state := 4;
  157.            when 2 .. 3 then
  158.           state := 3;
  159.            else -- 4
  160.            end;
  161.         end;
  162.      end;
  163.          if not end_of_input then
  164.             unread_character;
  165.          end;
  166.      debug
  167.         if state = 4 then
  168.            std_error.put_string("Error in INPUT_STREAM.read_integer.%N");
  169.            crash;
  170.         end;
  171.      end;
  172.      if sign then
  173.         last_integer := - last_integer;
  174.      end;
  175.       end;
  176.    
  177.    last_integer: INTEGER; 
  178.      -- Last integer read using `read_integer'.
  179.    
  180.    read_real is
  181.      -- Read a REAL and make the result available in `last_real'
  182.      -- and in `last_double'.
  183.      -- The integral part is available in `last_integer'.
  184.       require
  185.      not end_of_input
  186.       do
  187.      read_double;
  188.      last_real := last_double.to_real;
  189.       end;
  190.    
  191.    last_real: REAL; 
  192.      -- Last real read with `read_real'.
  193.    
  194.    read_double is
  195.      -- Read a DOUBLE and make the result available in 
  196.      -- `last_double'. 
  197.       require
  198.      not end_of_input
  199.       local
  200.      state: INTEGER;
  201.      sign: BOOLEAN;
  202.      ip, i: INTEGER;
  203.      -- state = 0 : waiting sign or first digit.
  204.      -- state = 1 : sign read, waiting first digit.
  205.      -- state = 2 : in the integral part.
  206.          -- state = 3 : in the fractional part.
  207.      -- state = 4 : end state.
  208.      -- state = 5 : error state.
  209.       do
  210.      from
  211.         tmp_read_double.clear;
  212.      until
  213.         state >= 4
  214.      loop
  215.         read_character;
  216.         inspect 
  217.            state
  218.         when 0 then
  219.            if last_character.is_separator then
  220.            elseif last_character.is_digit then
  221.           ip := last_character.value;
  222.           state := 2;
  223.            elseif last_character = '-' then
  224.           sign := true;
  225.           state := 1;
  226.            elseif last_character = '+' then
  227.           state := 1;
  228.            elseif last_character = '.' then
  229.           state := 3;
  230.            else
  231.           state := 5;
  232.            end;
  233.         when 1 then
  234.            if last_character.is_separator then
  235.            elseif last_character.is_digit then
  236.           ip := last_character.value;
  237.           state := 2;
  238.            else
  239.           state := 5;
  240.            end;
  241.         when 2 then
  242.            if last_character.is_digit then
  243.           ip := (ip * 10) + last_character.value;
  244.            elseif last_character = '.' then
  245.           state := 3;
  246.            else
  247.           state := 4;
  248.            end;
  249.         else -- 3 
  250.            if last_character.is_digit then
  251.           tmp_read_double.extend(last_character);
  252.            else
  253.           state := 4;
  254.            end;
  255.         end;
  256.         if end_of_input then
  257.            inspect
  258.           state
  259.            when 2 .. 4 then
  260.           state := 4;
  261.            else
  262.           state := 5;
  263.            end;
  264.         end;
  265.      end;
  266.          if not end_of_input then
  267.             unread_character;
  268.          end;
  269.      debug
  270.         if state = 5 then
  271.            std_error.put_string("Error in STD_FILE.read_double.%N");
  272.            crash;
  273.         end;
  274.      end;
  275.      from  
  276.         last_double := 0;
  277.         i := tmp_read_double.count;
  278.      until
  279.         i = 0
  280.      loop
  281.         last_double := (last_double + tmp_read_double.item(i).value) / 10;
  282.         i := i - 1;
  283.      end;
  284.      last_double := last_double + ip;
  285.      if sign then
  286.         last_double := - last_double;
  287.      end;
  288.       end;
  289.    
  290.    last_double: DOUBLE;
  291.      -- Last double read with `read_double'.
  292.    
  293. feature -- To read one line or one word at a time :
  294.  
  295.    last_string: STRING is
  296.      -- Access to a unique STRING to get the result computed
  297.      -- with `read_line', `read_word' or `newline'.
  298.      -- No new STRING is allocated.
  299.       once
  300.      !!Result.make(256);
  301.       end;
  302.    
  303.    read_line is
  304.      -- Read a complete line ended by '%N' or `end_of_input'. 
  305.      -- Make the result available in `last_string'.
  306.      -- Character '%N' is not added in `last_string'. 
  307.      --     
  308.      -- NOTE: the result is available in `last_string' without any 
  309.      --       memory allocation.
  310.       require
  311.      not end_of_input
  312.       do
  313.      last_string.clear;
  314.      read_line_in(last_string);
  315.       end;
  316.          
  317.    read_word is
  318.      -- Read a word using `is_separator' of class CHARACTER. 
  319.      -- Result is available in `last_string' (no allocation 
  320.      -- of memory).
  321.      -- Heading separators are automatically skipped.
  322.      -- Trailing separators are not skipped (`last_character' is
  323.      -- left on the first one).  
  324.      -- If `end_of_input' is encountered, Result can be the 
  325.      -- empty string.
  326.       require
  327.      not end_of_input
  328.       do
  329.      skip_separators;
  330.      from  
  331.         last_string.clear;
  332.      until
  333.         end_of_input or else
  334.         last_character.is_separator
  335.      loop
  336.         last_string.extend(last_character);
  337.         read_character;
  338.      end;
  339.       end;
  340.  
  341.    newline is
  342.      -- Consume input until newline ('%N') is found.
  343.      -- Corresponding STRING is stored in `last_string'.
  344.       local
  345.      stop: BOOLEAN;
  346.       do
  347.      from  
  348.         last_string.clear;
  349.         stop := end_of_input;
  350.      until
  351.         stop
  352.      loop
  353.         read_character;
  354.         if end_of_input or else last_character = '%N' then
  355.            stop := true;
  356.         else
  357.            last_string.extend(last_character);
  358.         end;
  359.      end;
  360.       end;
  361.  
  362. feature -- Other features :
  363.       
  364.    read_line_in(str: STRING) is
  365.      -- Same jobs as `read_line' but storage is directly done in `str'.
  366.      --
  367.       require
  368.      not end_of_input
  369.       deferred
  370.       end;
  371.  
  372.    read_word_using(separators: STRING) is
  373.      -- Same jobs as `read_word' using `separators'.
  374.       require 
  375.      not end_of_input;
  376.      separators /= void
  377.       do
  378.      -- Implemented by : Lars Brueckner 
  379.      -- (larsbruk@rbg.informatik.th-darmstadt.de)
  380.      skip_separators_using(separators);
  381.      from  
  382.         last_string.clear;
  383.      until
  384.         end_of_input or else
  385.         separators.has(last_character)
  386.      loop
  387.         last_string.extend(last_character);
  388.         read_character;
  389.      end;
  390.       end;
  391.     
  392.    read_tail_in(str: STRING) is
  393.      -- Read all remaining character of the file in `str'.
  394.       do
  395.      from
  396.      until
  397.         end_of_input
  398.      loop
  399.         read_character;
  400.         if not end_of_input then
  401.            str.extend(last_character);
  402.         end;
  403.      end;
  404.       ensure
  405.      end_of_input
  406.       end;
  407.  
  408. feature {NONE}
  409.  
  410.    eof_code: INTEGER is 
  411.       external "SmallEiffel"
  412.       end;
  413.  
  414.    read_byte(stream_pointer : POINTER): INTEGER is
  415.       external "SmallEiffel"
  416.       end;
  417.  
  418.    tmp_read_double: STRING is
  419.       once
  420.      !!Result.make(12);
  421.       end;
  422.  
  423. end -- INPUT_STREAM
  424.  
  425.